/**
 * Copyright (C) 2008 Christopher Allen Ogden
 *
 *     This file is part of Odysi.
 *
 *  Odysi is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Odysi is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Odysi.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdexcept>
#include <fstream>
#include <sstream>
#include "tileManager.h"

using std::runtime_error;
using std::range_error;
using std::ifstream;
using std::string;
using std::ostringstream;

void TileManager::load(unsigned int key, const std::string &fileName)
{
    clear(key);

    ifstream file(fileName.c_str(), std::ios_base::binary);
    if(!file)
        throw runtime_error("Could not open '" + fileName + "'.");

    string directory;
    if(!(file >> directory))
        throw runtime_error("Could not read the directory during the loading of '" + fileName + "'.");

    directory = string(PKGDATADIR) + "/" + directory;

    while(!file.eof())
    {
        int curTile = _tile[key].size();
        int walkable;
        int xOff;
        int yOff;
        int height;
        unsigned int numFrames;
        unsigned int ticksPerFrame;
        string name;

        ostringstream curTileNameStream;
        curTileNameStream << curTile;
        string curTileName(curTileNameStream.str());

        Tile tile;

        if(!(file >> height))
            break;
        if(!(file >> walkable))
            throw runtime_error("Could not read the flag field during the loading of '" + fileName + "' for tile number " + curTileName + ".");
        if(!(file >> numFrames))
            throw runtime_error("Could not read the number of frames during the loading of '" + fileName + "' for the tile number " + curTileName + ".");
        if(!(file >> ticksPerFrame))
            throw runtime_error("Could not read the number of ticks per frame during the loading of '" + fileName + "' for the tile number " + curTileName + ".");
        for(unsigned int curFrame = 0; curFrame < numFrames; curFrame++)
        {
            if(!(file >> name))
                throw runtime_error("Could not read the file name field during the loading of '" + fileName + "' for tile number " + curTileName + ".");
            if(!(file >> xOff))
                throw runtime_error("Could not read the X offset field during the loading of '" + fileName + "' for tile number " + curTileName + ".");
            if(!(file >> yOff))
                throw runtime_error("Could not read the Y offset field during the loading of '" + fileName + "' for tile number " + curTileName + ".");
            tile.addFrame(directory + '/' + name, xOff, yOff);
        }

        tile.setWalkable(walkable);
        tile.setTicksPerFrame(ticksPerFrame);
        tile.setHeight(height);
        _tile[key].push_back(tile);
    }
}

void TileManager::drawTile(unsigned int key, unsigned int id, unsigned int frame, int x, int y)
{
    // Make sure the ID is within range.
    if(id < 0 || id >= _tile[key].size())
    {
        std::ostringstream oss;
        oss << "Invalid index being drawn. Key: " << key << ", ID: " << id << ", Frame: " << frame << ", Size: " << _tile[key].size();
        throw range_error(oss.str());
    }

    // Draw the tile.
    _tile[key][id].draw(frame, x, y);
}

Tile *TileManager::getTile(unsigned int key, unsigned int id)
{
    if(id < 0 || id >= _tile[key].size())
    {
        std::ostringstream oss;
        oss << "Invalid index being requested. Key: " << key << ", ID: " << id << ", Size: " << _tile[key].size();
        throw range_error(oss.str());
    }

    return &_tile[key][id];
}

